#include "cheetah/model/triangle_mesh.h"

namespace cheetah {
namespace model {
using namespace math;
TriangleMesh::~TriangleMesh() {
  delete[] vertices_;
  delete[] normals_;
  delete[] tex_coords_;
  delete[] indices_;
  n_triangles_ = 0; 
  n_vertices_ = 0;
}		

void TriangleMesh::Transform(const Matrix4x4 &m) {
  Matrix4x4 inv_m = Inverse(m);
  for (int i = 0; i < n_vertices_; ++i) {
    this->set_vertex(i, m * this->vertex(i));
    this->set_normal(i, inv_m * this->normal(i));
  }
  bound_need_update_ = true;
}

void TriangleMesh::Scale(float scale) {
  for (int i = 0; i < n_vertices_; ++i) {
    this->set_vertex(i, this->vertex(i) * scale);
  }
  bound_need_update_ = true;
}

void TriangleMesh::Scale2Size(float size) {
  AABB box = this->Bound();
  Vector3 box_size = box.size();
  float max_size = max(max(box_size.x, box_size.y), box_size.z);
  this->Scale(size / max_size);
}

void TriangleMesh::Translate(const Vector3 &offset) {
  for (int i = 0; i < n_vertices_; ++i) {
    this->set_vertex(i, this->vertex(i) + offset);
  }
  bound_need_update_ = true;
}
void TriangleMesh::Translate2Pos(const Point &pos) {
  AABB box = this->Bound();
  Point center = box.minP + box.size() * 0.5f;
  Vector3 offset = pos - center;
  this->Translate(offset);
}

void TriangleMesh::ComputeBound() const {
  bound_ = AABB();
  for (int i = 0; i < n_vertices_; ++i) {
    bound_.Union(vertices_[i]);
  }
  bound_need_update_ = false;
}

AABB TriangleMesh::Bound() const {
  if (bound_need_update_) this->ComputeBound();
  return bound_;
}
} // model
} // cheetah
